
#ifndef _INCLUDE_MALLOC_H_
#define _INCLUDE_MALLOC_H_

#include <_ansi.h>
#include <sys/reent.h>

#define __need_size_t
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/* This version of struct mallinfo must match the one in
   libc/stdlib/mallocr.c.  */

struct mallinfo {
  int arena;    /* total space allocated from system */
  int ordblks;  /* number of non-inuse chunks */
  int smblks;   /* unused -- always zero */
  int hblks;    /* number of mmapped regions */
  int hblkhd;   /* total space in mmapped regions */
  int usmblks;  /* unused -- always zero */
  int fsmblks;  /* unused -- always zero */
  int uordblks; /* total allocated space */
  int fordblks; /* total non-inuse space */
  int keepcost; /* top-most, releasable (via malloc_trim) space */
};

/*
 *	struct mallocInfo isn't meet any standard such as POSIX,SVID2/XPG and so on.
 *  It is defined by LambdaRTL self to provide malloc user with enough malloc
 *  information.
 */
struct mallocInfo {
  int totalPoolSize;	/* total size allocated from system */
  int totalInuseSize;  	/* total inuse size */
  int totalInuseBlks;   /* total inuse blocks */
  int totalFreeSize;   	/* total free size */
  int totalFreeBlks;  	/* total free blocks */
  int accumMallocSize;  /* accumulative size assigned by malloc */
  int accumMallocBlks;  /* accumulative number of block assigned by malloc */
  int accumFreeSize;	/* accumulative size returned by free */
  int accumFreeBlks;	/* accumulative number of blocks returned by free */
  int maximAllocSize;  	/* maximum size of inuse block */
  int maximFreeSize; 	/* maximum size of non-inuse block  */
  int mallocFailures;	/* accumulative number of failures of malloc */
  int freeFailures;		/* accumulative number of failures of free */
};


struct Heap_Block
{
  unsigned long prev_size; /* Size of previous chunk (if free) with last bit used as flag */
  unsigned long size;      /* Size in bytes, with last bit used as flag. */
  struct Heap_Block* fd;   /* fd point to next block in current block list */
  struct Heap_Block* bk;  /* bk point to previous block in current block list */
};

#define MMU_PG_SIZE 4096
#define MMU_PGMALLOC_HEAD 12

/* The block head array is designed as a 10*32 array, with valid index from 1 to 320 */
#define BLOCK_HEAD_NUM 320
#define BLOCK_HEAD_MAJOR_NUM 10
#define BLOCK_HEAD_MINOR_NUM 32
#define BLOCK_HEAD_MINOR_WIDTH 5
#define BLOCK_HEAD_MAX_INDEX 320
#define BLOCK_HEAD_MIN_INDEX 1

#define BLOCK_IN_USE 1 /* the block is being used by user*/
#define BLOCK_MIN_SIZE 16 /* prev_size + size + fd + bk == 16 */
#define BLOCK_MEM_HEAD 8 /* prev_size + size == 8 */
#define BLOCK_MEM_HEAD_WIDTH 3

/* define macros for three levels */
#define LEVEL_ONE_BLOCK_SIZE 8
#define LEVEL_ONE_BLOCK_WIDTH 3
#define LEVEL_ONE_BLOCK_TOP 512
#define LEVEL_ONE_BLOCK_BOTTOM 8
#define LEVEL_ONE_BLOCK_ENTRY_NUM 64
#define LEVEL_ONE_BLOCK_FIRST_ENTRY 1
#define LEVEL_ONE_BLOCK_LAST_ENTRY 64

#define LEVEL_TWO_BLOCK_SIZE 64
#define LEVEL_TWO_BLOCK_WIDTH 6
#define LEVEL_TWO_BLOCK_TOP 12800
#define LEVEL_TWO_BLOCK_BOTTOM 576
#define LEVEL_TWO_BLOCK_ENTRY_NUM 192
#define LEVEL_TWO_BLOCK_FIRST_ENTRY 65
#define LEVEL_TWO_BLOCK_LAST_ENTRY 256


#define LEVEL_THREE_BLOCK_SIZE 1024
#define LEVEL_THREE_BLOCK_WIDTH 10
#define LEVEL_THREE_BLOCK_TOP 78336
#define LEVEL_THREE_BLOCK_BOTTOM 13824
#define LEVEL_THREE_BLOCK_ENTRY_NUM 64
#define LEVEL_THREE_BLOCK_FIRST_ENTRY 257
#define LEVEL_THREE_BLOCK_LAST_ENTRY 320

/* define bit value from bit 0 to bit 31 */
#define BLOCK_BIT_0 0x1
#define BLOCK_BIT_1 0x2
#define BLOCK_BIT_2 0x4
#define BLOCK_BIT_3 0x8
#define BLOCK_BIT_4 0x10
#define BLOCK_BIT_5 0x20
#define BLOCK_BIT_6 0x40
#define BLOCK_BIT_7 0x80

#define BLOCK_BIT_8 0x100
#define BLOCK_BIT_9 0x200
#define BLOCK_BIT_10 0x400
#define BLOCK_BIT_11 0x800
#define BLOCK_BIT_12 0x1000
#define BLOCK_BIT_13 0x2000
#define BLOCK_BIT_14 0x4000
#define BLOCK_BIT_15 0x8000

#define BLOCK_BIT_16 0x10000
#define BLOCK_BIT_17 0x20000
#define BLOCK_BIT_18 0x40000
#define BLOCK_BIT_19 0x80000
#define BLOCK_BIT_20 0x100000
#define BLOCK_BIT_21 0x200000
#define BLOCK_BIT_22 0x400000
#define BLOCK_BIT_23 0x800000

#define BLOCK_BIT_24 0x1000000
#define BLOCK_BIT_25 0x2000000
#define BLOCK_BIT_26 0x4000000
#define BLOCK_BIT_27 0x8000000
#define BLOCK_BIT_28 0x10000000
#define BLOCK_BIT_29 0x20000000
#define BLOCK_BIT_30 0x40000000
#define BLOCK_BIT_31 0x80000000


typedef struct HeapControl {
    unsigned long major ;
    unsigned long map[BLOCK_HEAD_MAJOR_NUM+1]; /* (10+1)*32 */
    struct Heap_Block *headptr[BLOCK_HEAD_NUM + 2];
    char inited ;
}HeapControl;

/* The routines.  */

/*
 *	mallocInfo Function isn't meet any standard such as POSIX,SVID2/XPG and so on.
 *  It is defined by LambdaRTL self to provide malloc user with enough malloc
 *  information.
 */
struct mallocInfo mallocInfo _PARAMS ((void));

extern _PTR malloc _PARAMS ((size_t));

extern _VOID free _PARAMS ((_PTR));

extern _PTR realloc _PARAMS ((_PTR, size_t));

extern _PTR calloc _PARAMS ((size_t, size_t));

extern struct mallinfo mallinfo _PARAMS ((void));

extern void malloc_stats _PARAMS ((void));
extern void _malloc_stats_r _PARAMS ((struct _reent *));

extern int mallopt _PARAMS ((int, int));
extern int _mallopt_r _PARAMS ((struct _reent *, int, int));

extern size_t malloc_usable_size _PARAMS ((_PTR));
extern size_t _malloc_usable_size_r _PARAMS ((struct _reent *, _PTR));

/* These aren't too useful on an embedded system, but we define them
   anyhow.  */

extern _PTR valloc _PARAMS ((size_t));
extern _PTR _valloc_r _PARAMS ((struct _reent *, size_t));

extern _PTR pvalloc _PARAMS ((size_t));
extern _PTR _pvalloc_r _PARAMS ((struct _reent *, size_t));

extern int malloc_trim _PARAMS ((size_t));
extern int _malloc_trim_r _PARAMS ((struct _reent *, size_t));

/* Some systems provide this, so do too for compatibility.  */

extern void cfree _PARAMS ((_PTR));

/* A compatibility routine for an earlier version of the allocator.  */

extern _VOID mstats _PARAMS ((char *));
extern _VOID _mstats_r _PARAMS ((struct _reent *, char *));

#ifdef __CYGWIN32__

/* Cygwin32 needs to be able to copy all the malloc information from
   the parent to the child.  However, cygwin32 does not normally copy
   any data in the DLL data section.  This routine handles copying
   that information.  */

extern int __malloc_copy _PARAMS ((int (*) (void *, void *, void *, int),
				   void *, int));
#endif /* __CYGWIN32 */


void *pgmalloc( unsigned long size);
int pgfree(void *pg);

/*  */
char generalHeapInitialize(HeapControl *pHC,void *start,unsigned long size);
char sysHeapInitialize(void *start,unsigned long size);


#ifdef __cplusplus
}
#endif

#endif /* _INCLUDE_MALLOC_H_ */
